﻿#include "DragonStatue.h"
#include "../../../Shared/Data/Stat.h"
#include "../../../Shared/Functions/Functions.h"
#include "../../../Shared/ServerPackets.h"
#include "../MapObject.h"
#include "../DelayedAction.h"

using namespace Server::MirDatabase;
namespace S = ServerPackets;

namespace Server::MirObjects::Monsters
{

    bool DragonStatue::getCanMove() const
    {
        return false;
    }

    DragonStatue::DragonStatue(MonsterInfo *info) : MonsterObject(info)
    {
        setDirection(static_cast<MirDirection>(std::min(static_cast<unsigned char>(5), static_cast<unsigned char>(getDirection()))));
    }

    void DragonStatue::Spawned()
    {
        if (Respawn != nullptr)
        {
            setDirection(static_cast<MirDirection>(std::min(static_cast<unsigned char>(5), static_cast<unsigned char>(Respawn->Info->Direction))));
        }

        MonsterObject::Spawned();
    }

    void DragonStatue::Turn(MirDirection dir)
    {
    }

    bool DragonStatue::Walk(MirDirection dir)
    {
        return false;
    }

    void DragonStatue::ProcessRoam()
    {
    }

    void DragonStatue::ProcessSearch()
    {
        if (!Sleeping)
        {
            MonsterObject::ProcessSearch();
        }
    }

    void DragonStatue::ProcessAI()
    {
        if (!Dead && Sleeping && getEnvir()->getTime() > WakeUpTime)
        {
            Sleeping = false;
            HP = Stats[Stat::HP];
            return;
        }

        MonsterObject::ProcessAI();
    }

    bool DragonStatue::InAttackRange()
    {
        return getCurrentMap() == getTarget()->getCurrentMap() && Functions::InRange(getCurrentLocation(), getTarget()->getCurrentLocation(), Info->ViewRange);
    }

    void DragonStatue::CompleteAttack(std::vector<std::any> &data)
    {
        if (getTarget() == nullptr || !getTarget()->IsAttackTarget(this) || getTarget()->getCurrentMap() != getCurrentMap() || getTarget()->Node == nullptr)
        {
            return;
        }

        S::ObjectRangeAttack *tempVar = new S::ObjectRangeAttack();
        tempVar->ObjectID = ObjectID;
        tempVar->Direction = getDirection();
        tempVar->Location = getCurrentLocation();
        tempVar->TargetID = getTarget()->ObjectID;
        Broadcast(tempVar);
        std::vector<MapObject*> targets = FindAllTargets(2, getTarget()->getCurrentLocation());
        if (targets.empty())
        {
//C# TO C++ CONVERTER TODO TASK: A 'delete tempVar' statement was not added since tempVar was passed to a method or constructor. Handle memory management manually.
            return;
        }

        for (int i = 0; i < targets.size(); i++)
        {
            int damage = GetAttackPower(Stats[Stat::MinDC], Stats[Stat::MaxDC]);
            if (damage == 0)
            {
                continue;
            }

            targets[i]->Attacked(this, damage, DefenceType::MAC);
        }

//C# TO C++ CONVERTER TODO TASK: A 'delete tempVar' statement was not added since tempVar was passed to a method or constructor. Handle memory management manually.
    }

    void DragonStatue::ProcessTarget()
    {
        if (getTarget() == nullptr || Sleeping)
        {
            return;
        }
        if (!getCanAttack())
        {
            return;
        }
        if (!FindNearby(Info->ViewRange))
        {
            return;
        }

        DelayedAction tempVar(DelayedType::Damage, getEnvir()->getTime() + 500);
        ActionList.push_back(&tempVar);
        ActionTime = getEnvir()->getTime() + 300;
        AttackTime = getEnvir()->getTime() + AttackSpeed;

        if (getEnvir()->getTime() < ShockTime)
        {
            setTarget(nullptr);
            return;
        }
    }

    int DragonStatue::Attacked(MonsterObject *attacker, int damage, DefenceType type)
    {
        return Sleeping ? 0 : MonsterObject::Attacked(attacker, damage, type);
    }

    int DragonStatue::Attacked(PlayerObject *attacker, int damage, DefenceType type, bool damageWeapon)
    {
        return Sleeping ? 0 : MonsterObject::Attacked(attacker, damage, type, damageWeapon);
    }

    int DragonStatue::Struck(int damage, DefenceType type)
    {
        return 0;
    }

    void DragonStatue::ChangeHP(int amount)
    {
        if (Sleeping)
        {
            return;
        }
        MonsterObject::ChangeHP(amount);
    }

    void DragonStatue::Die()
    {
        if (Dead || Sleeping)
        {
            return;
        }

        Sleeping = true;
        WakeUpTime = getEnvir()->getTime() + WakeDelay;
    }
}
